package com.onpositive.mediawiki.propertyparser;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;

import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;

import com.onpositive.data.IPropertyConstants;
import com.onpositive.knowledge.model.value.audits.AbstractAuditResult;
import com.onpositive.knowledge.model.values.ValueTraverser;
import com.onpositive.semantic.model.api.labels.TextProviderAdapter;
import com.onpositive.semantic.model.api.property.IProperty;
import com.onpositive.semantic.model.api.realm.AbstractFilter;
import com.onpositive.units.ParsedFileList;
import com.onpositive.units.ParsedIdent;
import com.onpositive.units.ParsedProperty;
import com.onpositive.units.ParsedValue;
import com.onpositive.units.ParsedValueSequence;
import com.onpositive.units.ValueCluster;
import com.onpositive.wikistorage.PictureManager;

public class ParsedDocument {

	public static final String PICTURE_LIST_PROPERTY_NAME = "files";
	private static final String CATEGORY_SEPARATOR = "\\;";

	private ParsedCategory category;
	private boolean isActual = true;

	private HashSet<String> parentCategoryNames = new HashSet<String>();
	private HashSet<ParsedDocument> parentCategories = new HashSet<ParsedDocument>();

	public ParsedDocument() {

	}

	public ParsedDocument(String name) {
		this.name = name;
	}

	public void setCategory(ParsedCategory category) {
		this.category = category;
	}

	public HashSet<ParsedDocument> getParentCategories() {

		if (category == null)
			return null;

		if (parentCategories == null || parentCategories.size() == 0)
			updateParentCategories();

		return parentCategories;
	}

	private void updateParentCategories() {
		if (category == null)
			return;

		if (parentCategories == null)
			parentCategories = new HashSet<ParsedDocument>();

		parentCategories.clear();
		HashSet<String> invalidDocumentNames = new HashSet<String>();
		for (String n : parentCategoryNames) {
			ParsedDocument pDoc = category.getParsedDocument(n);
			if (pDoc != null)
				parentCategories.add(pDoc);
			else
				invalidDocumentNames.add(n);
		}

		for (String n : invalidDocumentNames)
			parentCategoryNames.remove(n);

	}

	public void setParentCategories(Collection<ParsedDocument> parentCategories) {
		this.parentCategories = new HashSet<ParsedDocument>(parentCategories);

		updateParentCategoryNames();
	}

	private void updateParentCategoryNames() {
		if (parentCategories == null || parentCategories.size() == 0)
			return;

		parentCategoryNames.clear();
		for (ParsedDocument doc : parentCategories)
			parentCategoryNames.add(doc.getName());
	}

	private String defaultPicture = "";

	public String getDefaultPicture() {
		return defaultPicture;
	}

	public void setDefaultPicture(String defaultPicture) {
		if (checkPictureExistance(defaultPicture))
			this.defaultPicture = defaultPicture;
	}

	private String name = null;

	protected HashMap<String, ParsedProperty> props = new HashMap<String, ParsedProperty>();

	public HashMap<String, ParsedProperty> getProps() {
		return props;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return this.name;
	}

	public HashSet<String> getParentCategoryNames() {

		if (parentCategoryNames.size() == 0)
			return null;

		return parentCategoryNames;
	}

	public void setParentCategoryNames(Collection<String> parenCategories) {
		if(parenCategories==null)
			parenCategories = new ArrayList<String>();
		
		this.parentCategoryNames = new HashSet<String>(parenCategories);
		updateParentCategories();
	}

	public void addParentCategory(String name) {
		parentCategoryNames.add(name);

		updateParentCategories();
	}

	public String getParentCategoriesString() {

		if (this.parentCategoryNames.size() == 0)
			return "";

		String result = "";
		for (String cat : this.parentCategoryNames)
			result += cat + " " + CATEGORY_SEPARATOR;

		return result.substring(0,
				result.length() - CATEGORY_SEPARATOR.length()).trim();
	}

	public void setParentCategoriesString(String _s) {
		String s = _s.trim();
		if (s == null || s.length() == 0)
			return;

		String[] catArr = s.split(CATEGORY_SEPARATOR);
		this.parentCategoryNames.clear();
		for (String cat : catArr)
			if (cat.length() > 0){
				String trim = cat.trim();
				if (trim.endsWith("\\")) {
					trim=trim.substring(0,trim.length()-1).trim();
				}
						
					
				this.parentCategoryNames.add(trim);
			}

		updateParentCategories();
	}

	public void addProperty(ParsedProperty property) {
		props.put(property.getName(), property);
	}

	public ParsedProperty getPropertyForContribution(String propName) {
		ParsedProperty prop = props.get(propName);
		if (prop == null) {
			prop = new ParsedProperty(propName);
			props.put(propName, prop);
		}
		return prop;
	}

	public ParsedProperty getProperty(String propName) {
		return props.get(propName);
	}

	boolean checkPictureExistance(String path) {

		return PictureManager.getInstance(category.getRootPath())
				.checkPicturePresence(path, this.name);
	}

	public String getRootParh() {
		return category != null ? category.getRootPath() : null;
	}

	public void setDefaultPicture() {
		ParsedProperty prop = this.getProperty(PICTURE_LIST_PROPERTY_NAME);
		if (prop == null)
			return;

		ArrayList<String> wikiPaths = new ArrayList<String>();
		for (ParsedValue val : prop.values) {
			if (!(val instanceof ParsedFileList))
				continue;

			ArrayList<String> lst = (ArrayList<String>) val.value();
			for (String s : lst)
				wikiPaths.add(s);
		}
		if (wikiPaths.size() == 0)
			return;

		for (String str : wikiPaths) {
			if (str.startsWith("http:"))
				continue;

			if (!PictureManager.getInstance(category.getRootPath())
					.checkPicturePresence(str, this.name))
				continue;

			this.defaultPicture = str;
			break;
		}

	}

	public static class DefaultPictureExistanceFilter extends AbstractFilter {

		@Override
		public boolean accept(Object element) {
			try {
				String defaultpicture = ((ParsedDocument) element)
						.getDefaultPicture();
				return !(defaultpicture != null && defaultpicture.length() > 0);
			} catch (ClassCastException e) {
				return true;
			}
		}
	}

	public static class NameLabelProvider extends TextProviderAdapter {

		@Override
		public String getText(Object object) {
			if (object != null) {
				return ((ParsedDocument) object).getName();
			}
			return "null";
		}

		@Override
		public String getDescription(Object object) {
			return getText(object);
		}

	}

//	public void extractLinks(ParsedCategory _category) {
//		ArrayList<String> ownLinks = getOwnLinks();
//		HashSet<String> categoryLinks = _category.getLinks();
//		HashSet<String> categoryLinksCaptions = _category.getLinkCaptions();
//		
//		for ( int i = 0 ; i < ownLinks.size() ; i += 2 ) {
//			
//			String ref = ownLinks.get(i) ;
//			String caption = ownLinks.get(i+1) ;
//			
//			if( ref != null && ref.length() != 0 )
//				categoryLinks.add( ref );
//			
//			if( caption != null && caption.length() != 0 )
//				categoryLinksCaptions.add( caption );
//		}
//	}

	public HashMap<String,ArrayList<String>> getOwnLinks() {

		final ArrayList<String> links = new ArrayList<String>();

		ValueTraverser vt = new ValueTraverser() {

			@Override
			@SuppressWarnings("unchecked")
			protected void process(IProperty prop, Object val, Map<String,Object> metaInfo, int index)
			{
				ParsedValue pv = (ParsedValue) val;
				String id = pv.getId();

				ParsedIdent pi = null;
				if (id.equals(ParsedIdent.ID))
					pi = (ParsedIdent) val;

				else if (id.equals(ValueCluster.ID)) {
					String valType = pv.getMeta().getSingleValue(ParsedValue.META_KEY_VALUE_TYPE, String.class, null);
					if (valType.equals(ParsedIdent.ID)) {
						ValueCluster<ParsedIdent> vc = (ValueCluster<ParsedIdent>) val;
						pi = vc.getTargetValue();
					}
				}

				if (pi == null)
					return;

				String ref = pi.getRef();
				String caption = pi.getCaption();
				links.add(ref);
				links.add(caption);
			}

			@Override
			protected Class<?>[] createTargetClasses() {
				return new Class<?>[] { ParsedIdent.class, ValueCluster.class };
			}

			@Override
			protected Class<?>[] createNecessaryClasses() {
				return new Class<?>[]{ ParsedIdent.class, ValueCluster.class };
			}
		};

		HashMap<String,ArrayList<String>> result = new HashMap<String, ArrayList<String>>() ;
		for (ParsedProperty prop : this.props.values()) {
			
			String propName = prop.getName();		
				
			if( propName.equals( IPropertyConstants.TEXT_CONTENT_PROPERTY_NAME ) )
				continue ;			
			
			LinkedHashSet<ParsedValue> values = prop.getValues();
			links.clear() ;
			vt.iterateValues(null, values, false, null, 0);
			
			if( links.size() != 0 )
				result.put(propName, new ArrayList<String>( links ) ) ;
		}
		return result;
	}	

	public boolean isActual() {
		return isActual;
	}

	public void setActual(boolean isActual) {
		this.isActual = isActual;
	}

	public ParsedCategory getCategory() {
		return category;
	}
}
